/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "../../stdafx.h"
#include "../../include/core/FCString.h"

namespace FaceCat{
    fcwstring::fcwstring() : m_str(m_buffer){
        m_buffer[0] = '\0';
    }

    fcwstring::fcwstring(const wchar_t *str, int len) : m_str(m_buffer){
        m_buffer[0] = '\0';
        assign(str, len);
    }

    fcwstring::fcwstring(const fcwstring& str) : m_str(m_buffer){
        m_buffer[0] = '\0';
        assign(str.m_str);
    }

    fcwstring::~fcwstring(){
        if( m_str != m_buffer ){
            free(m_str);
            m_str = 0;
        }
    }

    int fcwstring::length() const{
        return (int)_tcslen(m_str);
    }

    fcwstring::operator wchar_t*() const {
        return m_str;
    }

    fcwstring fcwstring::append(const wchar_t *str){
       int newLen = length() + (int)wcslen(str);
       if(newLen >= 63) {
           if(m_str == m_buffer) {
               m_str = static_cast<wchar_t*>(malloc((newLen + 1) * sizeof(wchar_t)));
               wcscpy(m_str, m_buffer);
               wcscat(m_str, str);
           }else {
               m_str = static_cast<wchar_t*>(realloc(m_str, (newLen + 1) * sizeof(wchar_t)));
               wcscat(m_str, str);
           }
       }else {
           if(m_str != m_buffer) {
               free(m_str);
               m_str = m_buffer;
           }
           wcscat(m_buffer, str);
       }
       return *this;
    }

    void fcwstring::assign(const wchar_t *str, int len){
        if(!str){
            str = L"";
        }
        len = (len < 0 ? (int) wcslen(str) : len);
        if(len < 63) {
            if(m_str != m_buffer) {
                free(m_str);
                m_str = m_buffer;
            }
        }
        else if( len > length() || m_str == m_buffer ) {
            if(m_str == m_buffer){
                m_str = 0;
            }
            m_str = static_cast<wchar_t*>(realloc(m_str, (len + 1) * sizeof(wchar_t)));
        }
        wcsncpy(m_str, str, len);
        m_str[len] = '\0';
    }

    bool fcwstring::isEmpty() const {
        return m_str[0] == '\0';
    }

    void fcwstring::empty() {
        if(m_str != m_buffer){
            free(m_str);
        }
        m_str = m_buffer;
        m_buffer[0] = '\0';
    }

    wchar_t* fcwstring::c_str() const{
        return m_str;
    }

    wchar_t fcwstring::at(int index) const{
        return m_str[index];
    }

    wchar_t fcwstring::operator[] (int index) const{
        return m_str[index];
    }

    const fcwstring& fcwstring::operator=(const fcwstring& src){
        assign(src);
        return *this;
    }

    const fcwstring& fcwstring::operator=(const wchar_t *str){
        if (str){
            assign(str);
        }else{
            empty();
        }
        return *this;
    }

    const fcwstring& fcwstring::operator=(const wchar_t ch){
        empty();
        m_buffer[0] = ch;
        m_buffer[1] = '\0';
        return *this;
    }

    fcwstring fcwstring::operator+(const fcwstring& str) const{
        fcwstring sTemp = *this;
        sTemp.append(str);
        return sTemp;
    }

    fcwstring fcwstring::operator+(const wchar_t *str) const{
        if (str){
            fcwstring sTemp = *this;
            sTemp.append(str);
            return sTemp;
        }
        return *this;
    }

    const fcwstring& fcwstring::operator+=(const fcwstring& str){
        append(str);
        return *this;
    }

    const fcwstring& fcwstring::operator+=(const wchar_t *str){
        if (str){
            append(str);
        }
        return *this;
    }

    const fcwstring& fcwstring::operator+=(const wchar_t ch){
        wchar_t str[] = { ch, '\0' };
        append(str);
        return *this;
    }

    bool fcwstring::operator == (const wchar_t *str) const { return (compare(str) == 0); };
    bool fcwstring::operator != (const wchar_t *str) const { return (compare(str) != 0); };
    bool fcwstring::operator <= (const wchar_t *str) const { return (compare(str) <= 0); };
    bool fcwstring::operator <  (const wchar_t *str) const { return (compare(str) <  0); };
    bool fcwstring::operator >= (const wchar_t *str) const { return (compare(str) >= 0); };
    bool fcwstring::operator >  (const wchar_t *str) const { return (compare(str) >  0); };

    bool fcwstring::operator == (const fcwstring& str) const { return (compare(str) == 0); };
    bool fcwstring::operator != (const fcwstring& str) const { return (compare(str) != 0); };
    bool fcwstring::operator <= (const fcwstring& str) const { return (compare(str) <= 0); };
    bool fcwstring::operator <  (const fcwstring& str) const { return (compare(str) <  0); };
    bool fcwstring::operator >= (const fcwstring& str) const { return (compare(str) >= 0); };
    bool fcwstring::operator >  (const fcwstring& str) const { return (compare(str) >  0); };

    void fcwstring::set(int index, wchar_t ch){
        m_str[index] = ch;
    }

    int fcwstring::compare(const wchar_t *str) const {
        return _tcscmp(m_str, str);
    }

    int fcwstring::compare(const fcwstring& str) const {
        return _tcscmp(m_str, str.c_str());
    }

    fcwstring fcwstring::toUpper() {
        _tcsupr(m_str);
        return *this;
    }

    fcwstring fcwstring::toLower() {
        _tcslwr(m_str);
        return *this;
    }

    fcwstring fcwstring::substr(int pos, int len) const{
        return fcwstring(m_str + pos, len);
    }

    int fcwstring::find(const wchar_t *str, int pos /*= 0*/) const{
        wchar_t* p = _tcsstr(m_str + pos, str);
        if(!p ){
            return -1;
        }
        return (int)(p - m_str);
    }

    int fcwstring::rfind(const wchar_t *str, int pos /*= 0*/) const{
        int index = -1;
        while(true){
            int idx = find(str, pos);
            if(idx == -1){
                break;
            }else{
                index = idx;
            }
            pos = idx + 1;
            if(pos > length() - 1){
                break;
            }
        }
        return index;
    }

    int fcwstring::find(const fcwstring& str, int pos /*= 0*/) const{
        wchar_t* p = _tcsstr(m_str + pos, str.c_str());
        if(!p ){
            return -1;
        }
        return (int)(p - m_str);
    }

    int fcwstring::rfind(const fcwstring& str, int pos /*= 0*/) const{
        int index = -1;
        while(true){
            int idx = find(str, pos);
            if(idx == -1){
                break;
            }else{
                index = idx;
            }
            pos = idx + 1;
            if(pos > length() - 1){
                break;
            }
        }
        return index;
    }

    int fcwstring::find(wchar_t ch, int pos /*= 0*/) const{
        wchar_t *p = _tcschr(m_str + pos, ch);
        if(!p){
            return -1;
        }
        return (int)(p - m_str);
    }

    int fcwstring::find_last_of(wchar_t ch, int pos) const{
        wchar_t *p = _tcsrchr(m_str, ch);
        if(!p){
            return -1;
        }
        int index = (int)(p - m_str);
        if(index < pos){
            return -1;
        }
        return index;
    }

    int fcwstring::replace(const wchar_t *from, const wchar_t *to){
        fcwstring temp;
        int count = 0;
        int pos = find(from);
        if( pos < 0 ){
            return 0;
        }
        int cFrom = (int) _tcslen(from);
        int cTo = (int) _tcslen(to);
        while(pos >= 0) {
            temp = substr(0, pos);
            temp += to;
            temp += substr(pos + cFrom);
            assign(temp);
            pos = find(from, pos + cTo);
            count++;
        }
        return count;
    }

    fcstring::fcstring() : m_str(m_buffer){
        m_buffer[0] = '\0';
    }

    fcstring::fcstring(const char *str, int len) : m_str(m_buffer){
        m_buffer[0] = '\0';
        assign(str, len);
    }

    fcstring::fcstring(const fcstring& str) : m_str(m_buffer){
        m_buffer[0] = '\0';
        assign(str.m_str);
    }

    fcstring::~fcstring(){
        if( m_str != m_buffer ){
            free(m_str);
        }
    }

    int fcstring::length() const{
        return (int)strlen(m_str);
    }

    fcstring::operator char*() const {
        return m_str;
    }

    fcstring fcstring::append(const char *str){
        int newLen = length() + (int)strlen(str);
        if(newLen >= 63) {
            if(m_str == m_buffer) {
                m_str = static_cast<char*>(malloc((newLen + 1) * sizeof(char)));
                strcpy(m_str, m_buffer);
                strcat(m_str, str);
            }else {
                m_str = static_cast<char*>(realloc(m_str, (newLen + 1) * sizeof(char)));
                strcat(m_str, str);
            }
        }else {
            if(m_str != m_buffer) {
                free(m_str);
                m_str = m_buffer;
            }
            strcat(m_buffer, str);
        }
        return *this;
    }

    void fcstring::assign(const char *str, int len){
        if(!str){
            str = "";
        }
        len = (len < 0 ? (int) strlen(str) : len);
        if(len < 63) {
            if(m_str != m_buffer) {
                free(m_str);
                m_str = m_buffer;
            }
        }
        else if( len > length() || m_str == m_buffer ) {
            if(m_str == m_buffer){
                m_str = 0;
            }
            m_str = static_cast<char*>(realloc(m_str, (len + 1) * sizeof(char)));
        }
        strncpy(m_str, str, len);
        m_str[len] = '\0';
    }

    bool fcstring::isEmpty() const {
        return m_str[0] == '\0';
    }

    void fcstring::empty() {
        if(m_str != m_buffer){
            free(m_str);
        }
        m_str = m_buffer;
        m_buffer[0] = '\0';
    }

    char* fcstring::c_str() const{
        return m_str;
    }

    char fcstring::at(int index) const{
        return m_str[index];
    }

    char fcstring::operator[] (int index) const{
        return m_str[index];
    }

    const fcstring& fcstring::operator=(const fcstring& src){
        assign(src);
        return *this;
    }

    const fcstring& fcstring::operator=(const char *str){
        if (str){
            assign(str);
        }else{
            empty();
        }
        return *this;
    }

    const fcstring& fcstring::operator=(const char ch){
        empty();
        m_buffer[0] = ch;
        m_buffer[1] = '\0';
        return *this;
    }

    fcstring fcstring::operator+(const fcstring& str) const{
        fcstring sTemp = *this;
        sTemp.append(str);
        return sTemp;
    }

    fcstring fcstring::operator+(const char *str) const{
        if (str){
            fcstring sTemp = *this;
            sTemp.append(str);
            return sTemp;
        }
        return *this;
    }

    const fcstring& fcstring::operator+=(const fcstring& str){
        append(str);
        return *this;
    }

    const fcstring& fcstring::operator+=(const char *str){
        if (str){
            append(str);
        }
        return *this;
    }

    const fcstring& fcstring::operator+=(const char ch){
        char str[] = { ch, '\0' };
        append(str);
        return *this;
    }

    bool fcstring::operator == (const char *str) const { return (compare(str) == 0); };
    bool fcstring::operator != (const char *str) const { return (compare(str) != 0); };
    bool fcstring::operator <= (const char *str) const { return (compare(str) <= 0); };
    bool fcstring::operator <  (const char *str) const { return (compare(str) <  0); };
    bool fcstring::operator >= (const char *str) const { return (compare(str) >= 0); };
    bool fcstring::operator >  (const char *str) const { return (compare(str) >  0); };
    bool fcstring::operator == (const fcstring& str) const { return (compare(str) == 0); };
    bool fcstring::operator != (const fcstring& str) const { return (compare(str) != 0); };
    bool fcstring::operator <= (const fcstring& str) const { return (compare(str) <= 0); };
    bool fcstring::operator <  (const fcstring& str) const { return (compare(str) <  0); };
    bool fcstring::operator >= (const fcstring& str) const { return (compare(str) >= 0); };
    bool fcstring::operator >  (const fcstring& str) const { return (compare(str) >  0); };

    void fcstring::set(int index, char ch){
        m_str[index] = ch;
    }

    int fcstring::compare(const char *str) const {
        return strcmp(m_str, str);
    }

    int fcstring::compare(const fcstring& str) const {
        return strcmp(m_str, str.c_str());
    }

    fcstring fcstring::toUpper() {
        _strupr(m_str);
        return *this;
    }

    fcstring fcstring::toLower() {
        _strlwr(m_str);
        return *this;
    }

    fcstring fcstring::substr(int pos, int len) const{
        return fcstring(m_str + pos, len);
    }

    int fcstring::find(const char *str, int pos /*= 0*/) const{
        char* p = strstr(m_str + pos, str);
        if(!p ){
            return -1;
        }
        return (int)(p - m_str);
    }

    int fcstring::rfind(const char *str, int pos /*= 0*/) const{
        int index = -1;
        while(true){
            int idx = find(str, pos);
            if(idx == -1){
                break;
            }else{
                index = idx;
            }
            pos = idx + 1;
            if(pos > length() - 1){
                break;
            }
        }
        return index;
    }

    int fcstring::find(const fcstring& str, int pos /*= 0*/) const{
        char* p = strstr(m_str + pos, str.c_str());
        if(!p ){
            return -1;
        }
        return (int)(p - m_str);
    }

    int fcstring::rfind(const fcstring& str, int pos /*= 0*/) const{
        int index = -1;
        while(true){
            int idx = find(str, pos);
            if(idx == -1){
                break;
            }else{
                index = idx;
            }
            pos = idx + 1;
            if(pos > length() - 1){
                break;
            }
        }
        return index;
    }

    int fcstring::find(char ch, int pos /*= 0*/) const{
        char *p = strchr(m_str + pos, ch);
        if(!p){
            return -1;
        }
        return (int)(p - m_str);
    }

    int fcstring::find_last_of(char ch, int pos) const{
        char *p = strrchr(m_str, ch);
        if(!p){
            return -1;
        }
        int index = (int)(p - m_str);
        if(index < pos){
            return -1;
        }
        return index;
    }

    int fcstring::replace(const char *from, const char *to){
        fcstring temp;
        int count = 0;
        int pos = find(from);
        if( pos < 0 ){
            return 0;
        }
        int cFrom = (int)strlen(from);
        int cTo = (int)strlen(to);
        while(pos >= 0) {
            temp = substr(0, pos);
            temp += to;
            temp += substr(pos + cFrom);
            assign(temp);
            pos = find(from, pos + cTo);
            count++;
        }
        return count;
    }
}
